<?php
/**
 * Created by PhpStorm.
 * User: dt
 * Date: 2016/12/21
 * Time: 11:44
 */
namespace app\base;

use app\utils\SessionUtil;
use Yii;
use yii\web\Response;
use yii\web\Controller;
use yii\base\Exception;

/**
 * 控制器基类
 * @package app\base
 */
class BaseController extends Controller
{
    //全局关闭csrf防御，接口无需csrf防御
    public $enableCsrfValidation = false;
    //存储request请求体
    public $body = [];
    //存储data
    public $data = [];
    //存储token
    public static $token = '';

    /**
     * 控制器初始化
     */
    public function init()
    {
        //跨域
        header('Access-Control-Allow-Origin: *');
        header("Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept,sign,timeNumber,random");
        header('Access-Control-Allow-Methods: GET, POST');
        //ajax返回json
        Yii::$app->response->format = Response::FORMAT_JSON;
    }

    /**
     * 鉴权
     * @param \yii\base\Action $action
     * @return bool
     */
    public function beforeAction($action)
    {
        if (parent::beforeAction($action)) {
            //请求方式，post检测
            $this->_validateMethod();
            //请求体，json格式检测
            $this->_validateBody();
            //token验证
            $this->_validateToken($action);
            //所有验证通过
            return true;
        }
        return false;
    }

    /**
     * token有效期、合法性验证
     */
    private function _validateTokenExp()
    {
        //有效期和合法性验证
        if (!SessionUtil::validate(static::$token)) {
            Yii::$app->cache->delete(static::$token);
            exit(json_encode($this->ajaxReturn('token_failure',[]),JSON_UNESCAPED_UNICODE));
        }
    }

    /**
     * token验证
     * @param $action
     */
    private function _validateToken($action)
    {
        //请求路由
        $route = [
            'controller' => $action->controller->id,
            'action' => $action->id,
        ];
        //安全路由
        $safe = Yii::$app->params['safe'];
        //非安全路由检测token
        if (!in_array("{$route['controller']}/{$route['action']}", $safe) && !in_array("{$route['controller']}/*", $safe)) {
            //token丢失
            !empty($this->body['token']) or exit(json_encode($this->ajaxReturn('token_missing')));
            //token赋值
            static::$token = $this->body['token'];
            //token有效性验证
            $this->_validateTokenExp();
        }
    }

    /**
     * 请求体，json格式检测
     */
    private function _validateBody()
    {
        if (!($body = json_decode(Yii::$app->request->getRawBody(), true))){
            exit(json_encode($this->ajaxReturn('http_body')));
        }
        $this->body = $body;
        $this->data = !empty($this->body['data']) ? $this->body['data'] : [];
    }

    /**
     * 请求方法，只支持POST
     */
    private function _validateMethod()
    {
        if (!Yii::$app->request->isPost) {
            exit(json_encode($this->ajaxReturn('request_method')));
        }
    }

    /**
     * 统一JSON返回
     * @param $errIndex
     * @param array $data
     * @return array
     * @throws Exception
     */
    protected function ajaxReturn($errIndex, $data = [])
    {
        if (empty(Yii::$app->params['error'][$errIndex])) {
            $errorMsg = json_encode([
                'code' => Yii::$app->params['error']['params_error']['code'],
                'message' => "未找到返回信息索引[{$errIndex}]",
                'data' => [],
            ],JSON_UNESCAPED_UNICODE);
            throw new Exception($errorMsg);
        }
        $error = Yii::$app->params['error'][$errIndex];
        return [
            'code' => $error['code'],
            'message' => $error['info'],
            'data' => $data
        ];
    }

}
